package com.study.example.gameserver.socket.handler;

import com.sparrow.common.event.IEventInvoker;
import com.sparrow.event.core.EventBusImpl;
import com.sparrow.event.receiver.IEventReceiver;
import com.sparrow.socket.tcp.codec.Request;
import com.sparrow.common.thread.IoThreadPool;
import com.sparrow.common.thread.IdExecutorGroup;
import com.sparrow.event.model.Event;
import com.sparrow.socket.manager.PacketHandlerManager;
import com.sparrow.socket.tcp.session.impl.GameSession;
import com.sparrow.socket.tcp.session.manager.GameSessionManager;
import com.study.example.gameserver.socket.domain.ArgBuilder;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

@ChannelHandler.Sharable
public class GameServerHandler extends ChannelInboundHandlerAdapter {

    private static Logger logger = LoggerFactory.getLogger(GameServerHandler.class);

    @Autowired
    private PacketHandlerManager handlerManager;
    @Autowired
    private GameSessionManager sessionManager;
    @Autowired
    private IdExecutorGroup idExecutorGroup;
    @Autowired
    private IoThreadPool ioThreadPool;
    @Autowired
    private EventBusImpl eventBus;

    private ArgBuilder argBuilder = new ArgBuilder();

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        GameSession session = new GameSession();
        session.setChannel(ctx.channel());
        ctx.channel().attr(GameSession.SESSION_KEY).set(session);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        GameSession session = ctx.channel().attr(GameSession.SESSION_KEY).get();
        if (session != null) {
            sessionManager.close(session);
        }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Request request = (Request) msg;
        Object msgPacket = request.getMsg();
        GameSession session = ctx.channel().attr(GameSession.SESSION_KEY).get();
        eventBus.walkInvokers(msgPacket.getClass(), invoker -> {
            Object[] args = argBuilder.buildArgs(session, invoker.getMethod(), msgPacket);
            Event.Builder builder = Event.newBuilder(msgPacket).args(args).async();
            if (session.getIdentity() != null) { //有玩家id的 使用id线程池绑定的执行器
                builder.executor(idExecutorGroup.takeExecutor((long)session.getIdentity()));
            } else { //登录验证，创建 等还未绑定玩家id 的走io线程池
                builder.executor(ioThreadPool.getExecutor());
            }
            eventBus.publish(builder.build());
        });
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //它通常出现在客户端主动关闭连接（如强制退出、断网、异常终止等）
        if (cause instanceof java.net.SocketException && cause.getMessage().contains("Connection reset")) {
            // 静默处理 Connection reset 异常，不打印堆栈
            return;
        }
        logger.error("连接异常:", cause);
        ctx.close();
    }


}
